import { HttpException, Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { CryptoUtil } from '../../common/utils/crypto.util';
import {
  PageSearchUserDto,
  UpdatePasswordDto,
  UserRegisterDto,
} from '../../dto/user/user-register.dto';
import { Role } from '../../entities/role.entity';
import { User } from '../../entities/user.entity';
import { In, Like, Repository } from 'typeorm';

@Injectable()
export class UserService {
  async onModuleInit() {
    if (await this.findOneByAccount('admin')) return;
    const role = await this.roleRepository.findOne({
      where: {
        roleCode: 'admin',
      },
    });
    console.log(role, 'role');
    if (!role) {
      const adminRole = this.roleRepository.create({
        roleName: '超级管理员角色',
        roleCode: 'admin',
        remark: '超级管理员角色',
      });

      await this.roleRepository.save(adminRole);
    }
    if (role) {
      const { account, password, username, roleIds } = {
        account: 'admin',
        password: this.cryptoUtil.encryptPassword('admin'),
        username: '系统管理员',
        roleIds: [role?.id],
      };
      // 初始化系统管理员
      this.registerUser(account, password, username, roleIds);

      return;
    }
  }
  // 注入 一个操作数据表，一个加密密码
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    private readonly cryptoUtil: CryptoUtil,
    @InjectRepository(Role)
    private readonly roleRepository: Repository<Role>,
  ) {}

  /**
   * 通过登录账号查询用户
   *
   * @param account 登录账号
   */
  async findOneByAccount(account: string): Promise<User> {
    const user = await this.userRepository.findOne({
      where: {
        account,
      },
    });
    return user;
  }

  async registerUser(
    account: string,
    password: string,
    username: string,
    roleIds: string[],
  ): Promise<User> {
    const roles = await this.roleRepository.find({
      where: { id: In(roleIds) },
    });

    console.log(roles, 'roles');

    // 创建用户
    const user = this.userRepository.create({
      account,
      password,
      username,
      roles,
    });

    const savedUser = await this.userRepository.save(user);

    return savedUser;
  }

  async assignRolesToUser(userId: string, roleIds: string[]): Promise<void> {
    console.log(userId, 'userId', roleIds);

    const user = await this.userRepository.findOneOrFail({
      where: { id: userId },
    });
    const roles = await this.roleRepository.find({
      where: { id: In(roleIds) },
    });
    console.log(userId, 'userId', roles);
    // 关联角色
    console.log(user, 'userRoles', roles);
    const userRole = this.userRepository.create({
      roles: roles,
    });

    await this.userRepository.save(userRole);
  }

  async getUserWithRoles(userId: string): Promise<User | undefined> {
    return this.userRepository.findOne({
      where: { id: userId },
      relations: ['roles'],
    });
  }

  // 获取用户信息
  async getUserInfo({ userId }): Promise<any> {
    const user = await this.userRepository.findOne({
      where: {
        id: userId,
      },
      relations: ['roles'],
    });

    return user;
  }

  /**
   * 查询用户
   *
   * @param userId 用户
   */
  async findOne(account: string): Promise<User | undefined> {
    // console.log("user service ts findone enter",account);
    const user = await this.userRepository.findOne({
      where: {
        account,
      },
      relations: ['roles'],
    });

    return user;
    // console.log("user service ts findone leave",user);
  }

  /**
   * 创建用户
   * @param user
   */
  async register(user: UserRegisterDto): Promise<void> {
    const existing = await this.findOneByAccount(user.account);
    if (existing) throw new HttpException('账户已经存在了', 406);
    const roles = await this.roleRepository.find({
      where: { id: In(user.roleIds) },
    });
    const newUser = this.userRepository.create();
    Object.assign(newUser, user);
    newUser.roles = roles;
    newUser.password = this.cryptoUtil.encryptPassword(user.password);
    await this.userRepository.save(newUser);
  }
  //修改密码
  async updatePassword(updatePasswordDto: UpdatePasswordDto): Promise<void> {
    const user = await this.userRepository.findOne({
      where: { id: updatePasswordDto.id },
    });
    if (!user) {
      throw new NotFoundException('User not found');
    }

    // 检查旧密码是否匹配
    if (
      !this.cryptoUtil.checkPassword(updatePasswordDto.password, user.password)
    ) {
      throw new HttpException(
        this.cryptoUtil.encryptPassword(updatePasswordDto.password) +
          '旧密码不匹配' +
          user.password,
        400,
      );
    }

    // 设置新密码并加密
    user.password = this.cryptoUtil.encryptPassword(
      updatePasswordDto.confirmPassword,
    );

    // 保存更新后的用户信息
    await this.userRepository.save(user);
  }

  //删除
  async remove(id: string): Promise<any> {
    const existing = await this.userRepository.findOne({
      where: { id },
    });
    if (!existing) {
      return `删除用户Id为${id}的用户不存在`;
    }

    await this.userRepository.remove(existing);
  }
  //更新
  async update(updatInput: UserRegisterDto) {
    const existing = await this.userRepository.findOne({
      where: {
        id: updatInput?.id,
      },
      relations: ['roles'],
    });
    const roles = await this.roleRepository.find({
      where: { id: In(updatInput.roleIds) },
    });
    if (!existing)
      throw new HttpException(`更新用户Id为${updatInput?.id}的用户不存在`, 406);
    // if (updatInput.account) existing.account = updatInput.account;
    // if (updatInput.username) existing.username = updatInput.username;
    // if (updatInput.avatar) existing.avatar = updatInput.avatar;
    Object.assign(existing, updatInput);
    // 更新角色信息
    if (updatInput.roleIds.length > 0) {
      // 添加新的角色
      existing.roles = roles;
    }
    return await this.userRepository.save(existing);
  }
  /**
   * 分页条件用户信息
   */
  async page(param: PageSearchUserDto): Promise<[Partial<User>[], number]> {
    const { pageSize, pageNo, id, roleIds, username, account, sex } = param;
    const where: any = {};
    if (id) where.id = id;
    if (username) where.username = Like(`%${username}%`);
    if (account) where.account = Like(`%${account}%`);
    if (roleIds) where.roleIds = Like(`%${roleIds}%`);
    if (sex) where.sex = Like(`%${sex}%`);

    const [usersWithRoles, total] = await this.userRepository.findAndCount({
      where,
      order: {
        createdTime: 'DESC',
      },
      relations: ['roles'],
      take: pageSize,
      skip: (pageNo - 1) * pageSize,
    });

    // 将角色信息筛选为所需字段
    const result = usersWithRoles.map((user) => {
      delete user.password;
      const { roles, ...userData } = user; // 将用户信息和角色信息分离
      const roleData = roles.map((role) => {
        return {
          id: role.id,
          roleName: role.roleName,
          roleCode: role.roleCode,
        };
      });
      return { ...userData, roles: roleData };
    });

    return [result, total];
  }

  async findOneWithPostsById(id: string): Promise<User> {
    return await this.userRepository.findOne({
      where: {
        id,
      },
      relations: ['posts'],
    });
  }

  async findAll(): Promise<UserRegisterDto[]> {
    const usersWithRoles = await this.userRepository.find({
      relations: ['roles'],
    });

    // 将角色信息筛选为所需字段
    const result = usersWithRoles.map((user) => {
      const { roles, ...userData } = user; // 将用户信息和角色信息分离
      const roleData = roles.map((role) => {
        return {
          id: role.id,
          roleName: role.roleName,
          roleCode: role.roleCode,
        };
      });
      return { ...userData, roleIds: roleData };
    });

    return result;
  }
}
